﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KQ.DCMMP.Common
{
    public class JaccardUtility
    {
        public static double Jaccard(string[] source1, string[] source2)
        {
            //两集合交集
            List<string> intersection = new List<string>();
            for (int i = 0; i < source1.Length; i++)
            {
                for (int j = 0; j < source2.Length; j++)
                {
                    if (!intersection.Contains(source1[i]))
                    {
                        if (source1[i].Equals(source2[j]))
                        {
                            intersection.Add(source1[i]);
                            break;
                        }
                    }
                }
            }

            //数据全集
            List<string> union = new List<string>();
            if (source1.Length > source2.Length)
            {
                for (int i = 0; i < source1.Length; i++)
                {
                    if (!union.Contains(source1[i]))
                    {
                        union.Add(source1[i]);
                    }
                }
                for (int i = 0; i < source2.Length; i++)
                {
                    if (!union.Contains(source2[i]))
                    {
                        union.Add(source2[i]);
                    }
                }
            }
            else
            {
                for (int i = 0; i < source2.Length; i++)
                {
                    if (!union.Contains(source2[i]))
                    {
                        union.Add(source2[i]);
                    }
                }
                for (int i = 0; i < source1.Length; i++)
                {
                    if (!union.Contains(source1[i]))
                    {
                        union.Add(source1[i]);
                    }
                }
            }

            //计算相似度
            return ((float)intersection.Count) / ((float)union.Count);
        }

        /// <summary>
        /// 获取数组间的相似度
        /// 此方法暂未测试成功
        /// </summary>
        /// <param name="source1"></param>
        /// <param name="source2"></param>
        /// <returns></returns>
        [Obsolete]
        public static double GetSimilarity(string[] source1, string[] source2)
        {
            ArrayList sourceArray1 = new ArrayList(source1);
            HashSet<string> hashSet1 = new HashSet<string>();
            for (int d = 0; d < sourceArray1.Count; d++)
            {
                hashSet1.Add(sourceArray1[d].ToString());
            }
            ArrayList array1 = new ArrayList();
            for (int f1 = 0; f1 < hashSet1.Count; f1++)
            {
                array1.Insert(f1, hashSet1.ElementAt(f1));
            }

            ArrayList sourceArray2 = new ArrayList(source2);
            HashSet<string> hashSet2 = new HashSet<string>();
            for (int y = 0; y < sourceArray2.Count; y++)
            {
                hashSet2.Add(sourceArray2[y].ToString());
            }
            ArrayList array2 = new ArrayList();
            for (int f2 = 0; f2 < hashSet2.Count; f2++)
            {
                array2.Insert(f2, hashSet2.ElementAt(f2));
            }

            //获取所有词组
            HashSet<string> union = new HashSet<string>();
            union.UnionWith(hashSet1);
            union.UnionWith(hashSet2);

            //两个词组之间的重合词组
            HashSet<string> inherits = new HashSet<string>();
            inherits.UnionWith(hashSet1);
            inherits.IntersectWith(hashSet2);

            //获取词频
            ArrayList wordfreq1 = new ArrayList();
            for (int q1 = 0; q1 < union.Count; q1++)
            {
                int z = 0;
                for (int w1 = 0; w1 < sourceArray1.Count; w1++)
                {
                    if (union.ElementAt(q1) == sourceArray1[w1].ToString())
                    {
                        z += 1;
                    }
                }
                wordfreq1.Insert(q1, z.ToString());
            }

            /*
            for (int w = 0; w < inherits.Count; w++)
            {
                int z = 0;
                for (int q = 0; q < sourceArray1.Count; q++)
                {
                    if (inherits.ElementAt(w) == sourceArray1[q].ToString())
                    {
                        z += 1;
                    }
                }
                wordfreq1.Insert(w, z.ToString());
            }
            */

            ArrayList wordfreq2 = new ArrayList();
            for (int q2 = 0; q2 < union.Count; q2++)
            {
                int z = 0;
                for (int w2 = 0; w2 < sourceArray2.Count; w2++)
                {
                    if (union.ElementAt(q2) == sourceArray2[w2].ToString())
                    {
                        z += 1;
                    }
                }
                wordfreq2.Insert(q2, z.ToString());
            }
            /*
            for (int w1 = 0; w1 < inherits.Count; w1++)
            {
                int z = 0;
                for (int q1 = 0; q1 < sourceArray2.Count; q1++)
                {
                    if (inherits.ElementAt(w1) == sourceArray2[q1].ToString())
                    {
                        z += 1;
                    }
                }
                wordfreq2.Insert(w1, z.ToString());
            }
            */

            //获取匹配度
            double pprodq = 0;
            double x = 0;
            double y1 = 0;
            for (int pp = 0; pp < wordfreq1.Count; pp++)
            {
                pprodq = pprodq + (Convert.ToDouble(wordfreq1[pp]) * Convert.ToDouble(wordfreq2[pp]));
                x = x + (Convert.ToDouble(wordfreq1[pp]) * Convert.ToDouble(wordfreq1[pp]));
                y1 = y1 + (Convert.ToDouble(wordfreq2[pp]) * Convert.ToDouble(wordfreq2[pp]));
            }

            double jaccard = 0;
            jaccard = pprodq / ((x + y1) - (pprodq));

            return jaccard;
        }
    }
}